﻿using System;
using System.Web;
using System.Xml.Linq;

namespace Als.Pay.WeixinPay
{
    public class QRUtils
    {
        private static string _appId = "";
        private static string _appsecret = "";
        private static string _mchId = "";
        private static string _key = "";
        static QRUtils()
        {
            initConfig();
        }

        private static void initConfig()
        {
            var path = HttpContext.Current.Server.MapPath("/Config/WxPayConfig.xml");
            XDocument doc = XDocument.Load(path);
            var config = doc.Element("Config");
            _appId = config.Element("AppId").Value; ;
            _mchId = config.Element("MchId").Value; ;
            _key = config.Element("Key").Value; ;
            _appsecret = config.Element("AppSecret").Value; ;
        }

        /// <summary>
        /// 微信JS支付所需参数构造
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="totalFee"></param>
        /// <param name="productInfo"></param>
        /// <param name="notifyUrl"></param>
        /// <param name="returnUrl"></param>
        /// <param name="openId"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static string SendRequestJS(
            string orderId,
            decimal totalFee,
            string productInfo,
            string notifyUrl,
            string returnUrl,
            string openId = null,
            string ip = "")
        {
            string parameterValue = "";
            string noncestr = "";
            string signKey = "";
            RequestHandler handler = new RequestHandler();
            handler.Init();
            parameterValue = TenPayUtil.GetTimestamp();
            noncestr = TenPayUtil.GetNoncestr();
            handler.SetParameter("appid", _appId);
            handler.SetParameter("mch_id", _mchId);
            handler.SetParameter("nonce_str", noncestr);
            handler.SetParameter("body", productInfo);
            handler.SetParameter("out_trade_no", orderId);
            handler.SetParameter("total_fee", ((int)(totalFee * 100M)).ToString());
            handler.SetParameter("spbill_create_ip", ip);
            handler.SetParameter("notify_url", notifyUrl);
            handler.SetParameter("trade_type", "JSAPI");
            handler.SetParameter("openid", openId);
            handler.SetParameter("sign", handler.CreateMd5Sign("key", _key));
            string data = handler.ParseXML();
            XDocument document = XDocument.Parse(TenPayV3.Unifiedorder(data));

            if (document == null)
                throw new ApplicationException("调用统一支付出错：请求内容：" + data);
            if (document.Element("xml").Element("return_code").Value == "FAIL")
                throw new ApplicationException("预支付失败：" + document.Element("xml").Element("return_msg").Value);
            if (document.Element("xml").Element("result_code").Value == "FAIL")
                throw new ApplicationException("预支付失败：" + document.Element("xml").Element("err_code_des").Value);

            string prepay_id = document.Element("xml").Element("prepay_id").Value;

            RequestHandler handlerKey = new RequestHandler();
            handlerKey.SetParameter("appId", _appId);
            handlerKey.SetParameter("timeStamp", parameterValue);
            handlerKey.SetParameter("nonceStr", noncestr);
            handlerKey.SetParameter("package", string.Format("prepay_id={0}", prepay_id));
            handlerKey.SetParameter("signType", "MD5");
            signKey = handlerKey.CreateMd5Sign("key", _key);
            string jsBridge = string.Format("WeixinJSBridge.invoke('getBrandWCPayRequest', {{'appId': '{0}','timeStamp': '{1}','nonceStr': '{2}','package': '{3}','signType': 'MD5','paySign': '{4}'}}, function (res) {{if (res.err_msg == 'get_brand_wcpay_request:ok') {{location.href='" + returnUrl + "'}}else alert('支付失败！')}});", new object[] { _appId, parameterValue, noncestr, string.Format("prepay_id={0}", prepay_id), signKey });
            return string.Format("javascript:{0}", jsBridge);
        }
        /// <summary>
        /// 生成微信PC端扫码支付所需要URL，用此来生成二维码
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="totalFee"></param>
        /// <param name="productInfo"></param>
        /// <param name="notifyUrl"></param>
        /// <param name="returnUrl"></param>
        /// <param name="openId"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static string SendRequest(
            string orderId, 
            decimal totalFee, 
            string productInfo, 
            string notifyUrl, 
            string returnUrl, 
            string openId = null,
            string ip="")
        {
            string noncestr = TenPayUtil.GetNoncestr();
            string parameterValue = DateTime.Now.ToString("yyyyMMddHHmmss");
            RequestHandler handler = new RequestHandler();
            handler.SetParameter("appid", _appId);
            handler.SetParameter("mch_id", _mchId);
            handler.SetParameter("device_info", string.Empty);
            handler.SetParameter("nonce_str", noncestr);
            handler.SetParameter("body", productInfo);
            handler.SetParameter("attach", string.Empty);
            handler.SetParameter("out_trade_no", orderId);
            handler.SetParameter("total_fee", ((int)(totalFee * 100M)).ToString());
            handler.SetParameter("spbill_create_ip", ip);
            handler.SetParameter("time_start", parameterValue);
            handler.SetParameter("time_expire", string.Empty);
            handler.SetParameter("goods_tag", string.Empty);
            handler.SetParameter("notify_url", notifyUrl);
            handler.SetParameter("trade_type", "NATIVE");
            handler.SetParameter("openid", openId);
            handler.SetParameter("product_id", orderId);
            string str4 = handler.CreateMd5Sign("key",_key);
            handler.SetParameter("sign", str4);
            string data = handler.ParseXML();
            XDocument document = XDocument.Parse(TenPayV3.Unifiedorder(data));
            if (document == null)
            {
                throw new Exception("调用统一支付接口(Native)时出错：" + data);
            }
            XElement element = document.Element("xml").Element("return_code");
            XElement element2 = document.Element("xml").Element("return_msg");
            if (element == null)
            {
                throw new Exception("调用统一支付接口(Native)时,返回参数异常");
            }
            if (!(element.Value == "SUCCESS"))
            {
                throw new Exception("调用统一支付接口(Native)时,接口返回异常:" + element2.Value);
            }
            element2 = document.Element("xml").Element("result_code");
            XElement element3 = document.Element("xml").Element("err_code_des");
            if (element2.Value != "SUCCESS")
            {
                throw new Exception("调用统一支付接口(Native)时,接口返回异常:" + element3.Value);
            }
            return document.Element("xml").Element("code_url").Value;
        }
    }
}
